<?php

//bozErp

class bozErp{

    static $bzCache = []; // 简单缓存

    # /// bzxxx /////////////////////////////////

    // 读取 com-Catset - 系列配置
    static function bzcset($pid, $sec='Belts'){ 
        $cfgs = self::bzcfg('Catset'); $cfg = $cfgs[$sec];
        $p2 = substr($pid, 0, 2); $p3 = substr($pid, 0, 3);
        if(isset($cfg[$pid])){
            $cfg1 = $cfg[$pid];
        }elseif(isset($cfg[$p3])){
            $cfg1 = $cfg[$p3];
        }elseif(isset($cfg[$p2])){
            $cfg1 = $cfg[$p2];
        }else{
            $cfg1 = '';
        }
        return $cfg1;
    }

    // 读取 com-Share - sec - tab|tbc - 数组
    static function bztbc($sec, $ext=''){
        $shcfg = self::bzcfg('Share');
        $sec1 = empty($shcfg[$sec]) ? [] : $shcfg[$sec];
        $tb1 = explode(',', empty($sec1["tab$ext"]) ? '' : $sec1["tab$ext"]);
        $tb2 = explode(',', empty($sec1["tbc$ext"]) ? '' : $sec1["tbc$ext"]);
        $res = [];
        foreach($tb1 as $k1=>$v1){
            $res[trim($v1)] = trim($tb2[$k1]);
        }
        return $res;
    }

    # /// bzxxx /////////////////////////////////

    // 读取 text [之前vb6配置需要:转utf-8] 
    static function bzutf8($dfp, $ext='.xml'){
        $ifp = str_replace("\\", "/", DIR_APP.$dfp.$ext);
        if(!file_exists($ifp)){ return ''; } 
        $istr = file_get_contents($ifp); 
        $istr = preg_replace('/\/\*(.*?)\*\//s','',$istr); // /*note*/ 多行注释
        //$istr = Encode::autoCSet($istr); // , $from='gbk', $to='utf-8'
        return $istr;
    }
    // 读取 .json 配置
    static function bzcfg($fp, $bk=''){ 
        if(isset($bzCache[$fp])){ return $bzCache[$fp]; }
        if($bk && $bk=='bom'){
            $istr = self::bzutf8("/bomcfg/bom-$fp", '.json');
            $res = json_decode($istr, 1); 
        }else{ // read($fp, $dir='config')
            $fp = "/dic/com-$fp.php";
            $res = require DIR_APP . $fp;
        }
        $bzCache[$fp] = $res;
        if($bk && $bk!='bom'){ return $res[$bk]; }
        return $res;
    }
    // 读取 .xml 模板框架
    static function bzxmfr($fk, $scnt=2, $sbase=1){
        $sTop1  = self::bzutf8('/xlstpl/1top-Frame');
        $sTab1  = self::bzutf8('/xlstpl/1ex-Sheet');
        $sStyle = self::bzutf8("/xlstpl/$fk-Style");
        $sDoc   = self::bzutf8("/xlstpl/$fk-Frame");
        $sSheets = "";
        if($scnt>0){
            for($i=0;$i<$scnt;$i++){
                $sSheets .= str_replace("{SheetNo}", "Sheet".($i+$sbase), $sTab1);
            }
        } // gbk
        $sDoc = str_replace("<!--{Worksheet}-->", $sDoc, $sTop1);
        $sDoc = str_replace("<!--{RowStyle}-->", $sStyle, $sDoc);
        $sDoc = str_replace("<!--{SheetNo}-->", $sSheets, $sDoc);
        return $sDoc;
    }

    # /// convert /////////////////////////////////

    static function b64Rnd($strCode, $de=0){
        if(empty($strCode)) return '';
        $strCode = $de ? strrev($strCode) : Encode::urlBase64($strCode, $de); 
        $rnd1 = ord(substr($strCode,-1)) % 6;
        if(empty($rnd1)){
            $rnd1 = 3;
        }elseif($rnd1==4){
            $rnd1 = 2;
        } 
        if($de){
            $strCode = substr($strCode,0,1) . substr($strCode,$rnd1+1);
            $res = Encode::urlBase64($strCode, $de);
        }else{
            $rnds = Basic::kidRand(0,$rnd1); 
            $strCode = substr($strCode,0,1) . $rnds . substr($strCode,1);
            $res = strrev($strCode); //echo "(<br>$rnd1:rnds=$rnds // $strCode )";
        }
        return $res;
    }
    static function pwdEnc($fmCode, $fmPass){
        global $_cbase;
        $fmCode = strtoupper(trim($fmCode));
        $fmPass = strtoupper(trim($fmPass));
        return self::b64Rnd($_cbase['ucfg']['rndSalt'] . $fmPass . $fmCode);
    }
    static function pwdCmp($fmCode, $fmPass, $dbPass){
        global $_cbase;
        $fmCode = strtoupper(trim($fmCode));
        $fmPass = strtoupper(trim($fmPass));
        $cmpPass = $_cbase['ucfg']['rndSalt'] . $fmPass . $fmCode;
        $decDb = self::b64Rnd($dbPass, 1);
        return ($cmpPass == $decDb); // global $_cbase; $_cbase['mkvs'] = $mkvs;
    }

    # /// stat/lock /////////////////////////////////

    static function statInord($dt){
        $db = db('erp'); 
        $sub1 = " AND act IN('order','done','stop')";
        $sub2 = " AND act IN('order','done','stop')"; // 'add','pchk','pout'
        //
        $sql = "SELECT COUNT(*) AS cnt0, SUM(`订单数量`) AS ordadd FROM {pmc_order} WHERE `下单时间` LIKE '$dt%' $sub1";
        $r1 = $db->get($sql,[],1); $row['ordadd'] = empty($r1['ordadd']) ? "0" : $r1['ordadd']; 
        $sql = "SELECT COUNT(*) AS cnt0, SUM(`订单数量`) AS ordend FROM {pmc_order} WHERE `客户交期` LIKE '$dt%' $sub1";
        $r1 = $db->get($sql,[],1); $row['ordend'] = empty($r1['ordend']) ? "0" : $r1['ordend'];
        //
        $sql = "SELECT COUNT(*) AS bomcnt, SUM(`订单数量`) AS bomsum FROM {pmc_order} WHERE `出图日期`='$dt' $sub1";
        $r1 = $db->get($sql,[],1); 
        $row['bomcnt'] = empty($r1['bomcnt']) ? "0" : $r1['bomcnt']; 
        $row['bomsum'] = empty($r1['bomsum']) ? "0" : $r1['bomsum']; 
        return $row;
    }

    static function lockChk($kid, $pid, $user=''){
        //return [];
        global $_cbase; $db = db('erp'); 
        $atime = date('Y-m-d H:i'); $aip = Basic::envIP();
        $auser = $user ? $user : (empty($_cbase['urow']['mname']) ? '-' : $_cbase['urow']['mname']);
        $lock = data('sys_elock', "kid='$kid' AND pid='$pid'", 1, '' , 'erp'); //  AND auser='$auser'
        if(empty($lock)){
            $vals = "'$kid','$pid','$atime','$auser','$aip'";
            $sqldo = "INSERT INTO {sys_elock} (kid,pid,atime,auser,aip) VALUES ($vals) ";
            $lock = $db->run($sqldo, []);
        }elseif($lock['auser']==$auser){ // 自己
            $lock['atime'] = '';
            $lock['self'] = '1';
        } //dump($lock);
        return $lock;
    } 
    static function lockDel($user='', $pid='', $kid=''){
        //return [];
        global $_cbase; $db = db('erp'); //$aip = Basic::envIP();
        $auser = $user ? $user : (empty($_cbase['urow']['mname']) ? '-' : $_cbase['urow']['mname']);
        $whr = "auser='$auser'" . ($pid?" AND pid='$pid'":"") . ($kid?" AND kid='$kid'":"");
        $sqldo = "DELETE FROM {sys_elock} WHERE $whr"; //echo $whr;
        $lock = $db->run($sqldo, []);
        return $lock;
    }

    # /// db-kid /////////////////////////////////

    // 2022-1116-0001     - ("{tab}", "", "D", 4)
    // BZXS-20221112-026  - ("{tab}", "BZXS", "D8", 3)
    // BZCG-20230719-088  - ("{tab}", "BZCG", "D8", 3, '单号')
    static function kidTDB($dtb='bom_main', $pre='', $tpl='D', $eno=3, $fid='kid'){
        if($tpl=='Org'){
            $tno = $pre;
        }else{
            if($tpl=='D8'){
                $tno = date('Ymd') . '-';
            }else{
                $tno = date('Y-md') . '-';
            }
            if($pre){ $tno = "$pre-$tno"; }
        }
        //
        $db = db('erp'); 
        $r1 = $db->get("SELECT `$fid` FROM {{$dtb}} WHERE `$fid` LIKE '$tno%' ORDER BY `$fid` DESC", [], 1);
        if(empty($r1[$fid])){ //echo "<br>1.$fid LIKE '$tno%'\n";
            $t2 = 1;
        }else{ //echo "<br>2.$fid LIKE '$tno%'\n";
            $t2 = str_replace($tno, '', $r1[$fid]); // 0009, 9989, ABCD kidRand
            $t2 = is_numeric($t2) ? intval($t2) + 1 : Basic::kidRand(4);
        }
        $re2 = substr("000$t2", -1*$eno); // kid9999($t2, $eno);
        return "$tno$re2";
    }
    static function knoTDB($dtb='purch_itmp', $fid='kid', $kid='', $cnt=0, $bi=0, $bm=0){
        if($cnt>0){ usleep(1000); $kid = Basic::kidTemp('md3h'); }
        $kid || $kid = Basic::kidTemp('md3h'); // 2023-727F-583V(14)
        if($bi && $bm){
            if($bm<10){
                $kid .= $bi.Basic::kidRand('',1);
            }elseif($bm<30){
                $kid .= Basic::fmtBase32('', $bi, 32, 1, '').Basic::kidRand('',1);
            }elseif($bm<960){ // & $bm<960
                $kid .= Basic::fmtBase32('', $bi, 32, 2, '');
            }else{
                $kid .= Basic::fmtBase32('', $bi, 32, 3, '');
            }
        }else{
            if($cnt>0){ $kid .= strlen($kid)>15 ? '' : Basic::kidRand('',2); }
        }
        //
        $db = db('erp'); 
        $r1 = $db->get("SELECT `$fid` FROM {{$dtb}} WHERE `$fid`='$kid'", [], 1);
        if(empty($r1)){
            return strtoupper($kid);
        }else{
            if($cnt<3){
                $kid = substr($kid,0,14).Basic::kidRand('',2);
            }else{
                $kid = substr($kid,0,13).Basic::kidRand('',3);
            } 
            return self::knoTDB($dtb, $fid, $kid, $cnt+1, $bi=0, $bm=0);
        }
    }

    // 写日志
    static function actlog($act='', $msg='', $no=0){
        global $_cbase; if(empty($_cbase['urow'])){ return 0; }
        $kid = bozErp::knoTDB('sys_logs', 'kid', ''); $db = db('erp');
        $atime = date('Y-m-d H:i'); $auser=$_cbase['urow']['mname']; $aip = Basic::envIP();
        $page = empty($_cbase['mkvs']['mkv']) ? $_SERVER['PHP_SELF'] : $_cbase['mkvs']['part'].':'.$_cbase['mkvs']['mkv'];
        $fids = "kid,page,act,msg"; $vals = "'$kid','$page','$act','$msg'"; 
        $sqldo = "INSERT INTO {sys_logs} ($fids, atime,auser,aip) VALUES ($vals, '$atime','$auser','$aip') "; 
        return $db->run($sqldo); 
    }

    static function nowUact($row=[]){
        $type = $row['类型']; $dep = $row['部门'];
        $prmExts = $row['exPerm']; 
        $exdp = $row['exDeps']; $tbdps = explode(',', "$dep,$exdp"); $tbdps = array_filter(array_unique($tbdps));
        //$pmExt = self::bztbc('userPerm'); 
        $pmDept = self::bztbc('userPerm', 'Dept'); 
        $shcfg = self::bzcfg('Share');
        $prmMods = $shcfg['userPerm']['defMods']; // ',home,';
        foreach($tbdps as $dp){ if($dp){
            $dpm = isset($pmDept[$dp]) ? $pmDept[$dp] : '';
            if($dpm){ $prmMods .= str_replace('+',',',$dpm) . ","; }
        } }
        $urow = [ 
            'utype'=>'erp', 'umod'=>"$type.$dep", 'uname'=>$row['账号'], 'mname'=>$row['姓名'], 'erpTel'=>$row['电话'], //'erpSSSS'=>'SSSS', 
            'erpHome'=>$row['DefHome'], 'erpSkin'=>$row['DefSkin'], 'erpType'=>$type, 'erpDep'=>$dep, 'prmMods'=>$prmMods, 'prmExts'=>$prmExts, 
        ]; 
        return $urow;
    }

    // 清理缓存
    static function clearTmps($ttl=9600){
        $time0 = time();
        echo " ##### Clear (temp) ##### <br>\n";
        $list = glob(DIR_DATA."/temp/*.*"); 
        foreach ($list as $file) { 
            if($file=='.'||$file=='..'||basename($file)=='_keep.txt'){ continue; } 
            if(!is_dir($file)){ 
                $mtime = filemtime($file); // fileatime
                $bsfp = basename($file); // 1800-9600
                if($time0-$mtime>9600){ 
                    unlink($file); 
                    echo "* !!! del : $bsfp<br>\n";
                }else{
                    echo "* ".date('H:i',$mtime)." [keep] $bsfp<br>\n";
                }
            }
        }
    }

    // 清理日志:$ttl=36天之前记录
    static function clearLogs($ttl=36){
        $time = time(); $td36 = $time - $ttl * 86400; // 36天以前
        $pre1 = Basic::kidTemp('md3h', $td36); 
        $db1 = db(); $db2 = db('erp');
        $sql1 = "DELETE FROM {active_login} WHERE atime<='$td36'"; // atime = 1687934034 
        $r1 = $db1->run($sql1); 
        $sql2 = "DELETE FROM {sys_logs} WHERE kid<='$pre1'"; // kid = 2023-624D-JN0GU4
        $r2 = $db2->run($sql2); 
        echo " ##### Clear (logs) ##### <br>\n";
        echo "* !!! ".json_encode($r1)." $sql1 <br>\n";
        echo "* !!! ".json_encode($r2)." $sql2 <br>\n";
    }

}

/*

*/
